<?php
/**
 * Created by nineton.
 * Description:黑名单服务类
 * User: sunnier
 * Email: xiaoyao_xiao@126.com
 * Date: 2019-12-01 12:46
 */
namespace app\common\service;

use QL\QueryList;
class CrawlRepoService extends BaseService
{
    protected $crawlRepoModel;

    protected $githubUrl='https://github.com';

    public function __construct()
    {
        parent::__construct();
        $this->crawlRepoModel=model('common/Repository');
    }

    /**
     * @param $lang
     * @param $date
     * Description:爬取github数据
     * Author:sunnier
     * Email:xiaoyao_xiao@126.com
     * 2020-11-02 11:30
     */
    public function crawler($lang,$date){
        if($lang=='all') {
            $url = $this->githubUrl . '/trending';
        }else{
            $url = $this->githubUrl . '/trending/' . $lang ;
        }
        $successFlag=true;
        $repolistArr=[];
        $msg='';
        try {
            libxml_use_internal_errors(true);
            $ql = QueryList::get($url, [
                'since'=>$date
            ], [
                'headers' => [
                    'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
                    'Accept'     => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
                    'Accept-Encoding' => 'gzip, deflate, br',
                ],
                'verify' => false
            ]);
            $ql->find('.Box article.Box-row')
                ->map(function ($repoStrObj) use (&$repolistArr) {
                    $title = trim($repoStrObj->find('.h3')
                        ->text(), '/r/n ');
                    $username = trim(explode('/', $title)[0]);
                    $repoName = trim(str_replace(["", " ", "\/t", PHP_EOL, "\/r"], ['', '', '', '', ''], explode('/', $title)[1]));
                    $relativeUrl = $repoStrObj->find('.h3')
                        ->find('a')
                        ->attr('href');
                    $currentPeriodStarsString = trim($repoStrObj->find('.float-sm-right')
                        ->text());
                    $builtByArr = [];
                    $repoStrObj->find('span:contains("Built by")')
                        ->find('[data-hovercard-type="user"]')->map(function ($userData) use (&$builtByArr) {
                            $altString = $userData->children('img')
                                ->attr('alt');
                            $avatarUrl = $userData->children('img')
                                ->attr('src');
                            $username = $altString ? $altString : '';
                            $builtByArr[] = [
                                'username' => str_replace('@', '', $username),
                                'href' => $this->githubUrl . $userData->attr('href'),
                                'avatar' => $avatarUrl
                            ];
                        });
                    $colorNode = $repoStrObj->find('.repo-language-color');
                    $langColor = $colorNode ? trim(str_replace('background-color:', '', $colorNode->attr('style'))) : '';
                    $langNode = $repoStrObj->find('[itemprop=programmingLanguage]');
                    $lang = $langNode ? trim($langNode->text()) : '';
                    $repolistArr[] = [
                        'author' => $username,
                        'name' => $repoName,
                        'avatar' => $this->githubUrl . '/' . $username . '.png',
                        'url' => $this->githubUrl . $relativeUrl,
                        'description' => $repoStrObj->find('p.my-1')
                            ->text() ? trim($repoStrObj->find('p.my-1')
                            ->text()) : '',
                        'language' => $lang,
                        'languageColor' => $langColor,
                        'stars' => $repoStrObj->find('a.muted-link')->eq(0)->text(),
                        'forks' => $repoStrObj->find('a.muted-link')->eq(1)->text(),
                        'currentPeriodStars' => intval(
                            str_replace(',', '', explode(' ', $currentPeriodStarsString)[0])),
                        'builtBy' => $builtByArr
                    ];
                });
        }catch (\Exception $e){
            $successFlag = false;
            $msg=$e->getMessage();
        }
        $nowTime=time();
        if($hasData=$this->crawlRepoModel->field('id,update_time')
            ->where('lang',$lang)
            ->where('date',$date)->find()){
            if(!$successFlag){
                if(!$this->crawlRepoModel->where('id',$hasData['id'])
                    ->update(['is_update'=>0,'msg'=>$msg,'update_time'=>time()])){
                    return [
                        'status'=>0,
                        'msg'=>'更新数据出错！'
                    ];
                }
            }else{
                if(!empty($repolistArr)) {
                    if (!$this->crawlRepoModel->where('id', $hasData['id'])
                        ->update(['content' => json_encode($repolistArr), 'is_update' => 1, 'update_time' =>$nowTime])) {
                        return [
                            'status' => 0,
                            'msg' => '更新数据出错！'
                        ];
                    }
                }
            }
        }else{
            $saveData = [
                'lang' => $lang,
                'date' => $date,
                'content' => json_encode($repolistArr),
                'update_time'=>$nowTime,
                'create_time'=>$nowTime
            ];
            if (!$this->crawlRepoModel->insert($saveData)) {
                return [
                    'status' => 0,
                    'msg' => '插入数据出错！'
                ];
            }
        }
        return [
            'status'=>1,
            'msg'=>'处理数据成功完成'
        ];
    }

    /**
     * @param $lang
     * @param $date
     * @return array
     * Description:获取对应的语言和日期列表
     * Author:sunnier
     * Email:xiaoyao_xiao@126.com
     * 2020-11-02 14:39
     */
    public function getList($lang,$date){
        $result=[];
        $resultRes=$this->crawlRepoModel
            ->field('id,content')->where('lang',$lang)
            ->where('date',$date)->find();
        if($resultRes) {
            return [
                'status' => 1,
                'msg' => '获取成功！',
                'data' => json_decode($resultRes['content'],'true')
            ];
        }else{
            return [
                'status' => 1,
                'msg' => '获取成功！',
                'data' => $result
            ];
        }
    }
}